package com.mikgonz.farkle;

public class Scorer {

	private int numOf1 = 0;
	private int numOf2 = 0;
	private int numOf3 = 0;
	private int numOf4 = 0;
	private int numOf5 = 0;
	private int numOf6 = 0;
	private int score = 0;

	public int calculate(int[] array) {
		int length = array.length;

		count(array);

		if (length == 6) {
			if (isStraight())
				return score(1500);
			if (isThreePair())
				return score(750);
			if (isSixOfAKind())
				return score(score);
		}

		scoreCombinations(length);

		return score(score);

	}

	private void scoreCombinations(int length) {

		if (length == 5 && isFiveOfAKind()) {

			return;
		}
		if (length == 4 && isFourOfAKind()) {

			return;
		}
		if (length == 3 && isThreeOfAKind()) {
			return;
		}

		if (isFiveOfAKind() || isFourOfAKind() || isThreeOfAKind())
			;

		scoreRemainders();
		return;

	}

	private boolean isThreeOfAKind() {
		if (numOf1 == 3) {
			score += 1000;
			numOf1 = 0;
		}
		if (numOf2 == 3)
			score += 200;
		if (numOf3 == 3)
			score += 300;
		if (numOf4 == 3)
			score += 400;
		if (numOf5 == 3) {
			score += 500;
			numOf5 = 0;
		}
		if (numOf6 == 3)
			score += 600;

		return (score != 0);
	}

	private void scoreRemainders() {
		score += numOf1 * 100;
		score += numOf5 * 50;
	}

	private boolean isSixOfAKind() {
		if (numOf1 == 6) {
			score = 10000; // Instant Win
			numOf1 = 0;
		}
		if (numOf2 == 6)
			score = 1600; // 200*2*2*2
		if (numOf3 == 6)
			score = 2400; // 300*2*2*2
		if (numOf4 == 6)
			score = 3200; // 400*2*2*2
		if (numOf5 == 6) {
			score = 4000; // 500*2*2*2
			numOf5 = 0;
		}
		if (numOf6 == 6)
			score = 4800; // 600*2*2*2

		return (score != 0);
	}

	private boolean isFourOfAKind() {
		if (numOf1 == 4) {
			score = 2000; // 1000*2
			numOf1 = 0;
		}
		if (numOf2 == 4)
			score = 400; // 200*2
		if (numOf3 == 4)
			score = 600; // 300*2
		if (numOf4 == 4)
			score = 800; // 400*2
		if (numOf5 == 4) {
			score = 1000; // 500*2
			numOf5 = 0;
		}
		if (numOf6 == 4)
			score = 1200; // 600*2

		return (score != 0);

	}

	private boolean isFiveOfAKind() {
		if (numOf1 == 5) {
			score = 4000; // 1000*2*2
			numOf1 = 0;
		}
		if (numOf2 == 5)
			score = 800; // 200*2*2
		if (numOf3 == 5)
			score = 1200; // 300*2*2
		if (numOf4 == 5)
			score = 1600; // 400*2*2
		if (numOf5 == 5) {
			score = 2000; // 500*2*2
			numOf5 = 0;
		}
		if (numOf6 == 5)
			score = 2400; // 600*2*2

		return (score != 0);

	}

	private boolean isThreePair() {
		int count = 0;

		if (numOf1 == 2)
			count++;
		if (numOf2 == 2)
			count++;
		if (numOf3 == 2)
			count++;
		if (numOf4 == 2)
			count++;
		if (numOf5 == 2)
			count++;
		if (numOf6 == 2)
			count++;

		return (count == 3);
	}

	private boolean isStraight() {

		return (numOf1 == 1 && numOf2 == 1 && numOf3 == 1 && numOf4 == 1
				&& numOf5 == 1 && numOf6 == 1);
	}

	public void reset() {
		numOf1 = 0;
		numOf2 = 0;
		numOf3 = 0;
		numOf4 = 0;
		numOf5 = 0;
		numOf6 = 0;
		score = 0;
	}

	// resets score before returning it
	private int score(int mScore) {
		int toReturn = mScore;
		reset();
		return toReturn;
	}

	public boolean isThreePair(int[] array) {
		count(array);
		return reset(isThreePair());
	}

	private void count(int[] array) {
		for (int j = 0; j < array.length; j++) {
			switch (array[j]) {
			case (1):
				numOf1++;
				break;
			case (2):
				numOf2++;
				break;
			case (3):
				numOf3++;
				break;
			case (4):
				numOf4++;
				break;
			case (5):
				numOf5++;
				break;
			case (6):
				numOf6++;
				break;
			}

		}

	}

	private boolean reset(boolean b) {
		reset();
		return b;
	}
}
